package hs.framework.opcClient.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import hs.framework.opcClient.entity.OPCServer;
import hs.framework.opcClient.mapper.OPCServerMapper;
import hs.framework.opcClient.service.IOPCServerService;
import hs.framework.opcClient.utils.Browser;
import hs.framework.opcClient.utils.ServerInfo;
import lombok.extern.log4j.Log4j2;
import org.jinterop.dcom.common.JIException;
import org.openscada.opc.dcom.da.OPCSERVERSTATE;
import org.openscada.opc.lib.common.AlreadyConnectedException;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.common.NotConnectedException;
import org.openscada.opc.lib.da.*;
import org.springframework.stereotype.Service;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
@Service
@Log4j2
public class OPCServerServiceImpl extends ServiceImpl<OPCServerMapper, OPCServer> implements IOPCServerService {

    private static HashMap<String,Server> serverMap = new HashMap<>();
    private static HashMap<String,AccessBase> accessBaseMap = new HashMap<>();

    /**
    * @Description 列出目标服务器上所有的opc服务器
    * @Return
    * @Author sxmz
    * @Date 2021/5/11 0011 下午 3:24
    */
    @Override
    public List<ServerInfo> getServers(OPCServer opcServer) throws Throwable {
        return Browser.listServer(opcServer.getHost(),"",opcServer.getUser(),opcServer.getPassword());
    }

    /**
    * @Description 连接到目标opc服务器
    * @Return
    * @Author sxmz
    * @Date 2021/5/11 0011 下午 3:26
    **/
    @Override
    public synchronized Server openServer(OPCServer opcServer) throws AlreadyConnectedException, JIException, UnknownHostException {
        Server server = serverMap.get(opcServer.getKeyWord());
        System.out.println("正在寻找服务器...");
        if (server!=null&&server.getServerState()!=null&&server.getServerState().getServerState()== OPCSERVERSTATE.OPC_STATUS_RUNNING){
            return server;
        } else {
            System.out.println("服务器正在连接...");
            final ConnectionInformation ci = new ConnectionInformation();
            ci.setHost(opcServer.getHost());         // 电脑IP
            ci.setDomain("");                  // 域，为空就行
            ci.setUser(opcServer.getUser());             // 电脑上自己建好的用户名
            ci.setPassword(opcServer.getPassword());
            ci.setClsid(opcServer.getClsId());
            // 启动服务
            server = new Server(ci, Executors.newSingleThreadScheduledExecutor());
//            AutoReconnectController controller = new AutoReconnectController(server);
            // 连接到服务
             server.connect();
//            controller.connect();
            //判断是否连接成功
            if (server!=null&&server.getServerState()!=null&&server.getServerState().getServerState()== OPCSERVERSTATE.OPC_STATUS_RUNNING){
                serverMap.put(opcServer.getKeyWord(),server);
                log.info(opcServer.getKeyWord()+" opc服务器连接成功！");
                try {
                    log.info("开始创建 write、read Group...");
                    Group writeGroup = server.addGroup("write");
                    Group readGroup = server.addGroup("read");
                    log.info("write、read Group 组创建成功！");
                } catch (NotConnectedException e) {
                    log.error("opc服务器未连接！创建group失败...");
                    e.printStackTrace();
                } catch (DuplicateGroupException e) {
                    log.error("请不要创建重复组名！");
                    e.printStackTrace();
                }
            }else {
                log.error("opc服务器连接不成功！请检查参数!");
            }

            System.out.println(server.getServerState());
            return server;
        }
    }

    /**
    * @Description 获取opc服务器的连接状态
    * @Return
    * @Author sxmz
    * @Date 2021/5/11 0011 下午 3:45
    **/
    @Override
    public synchronized AccessBase getAccessBase(OPCServer opcServer) throws DuplicateGroupException, NotConnectedException, JIException, UnknownHostException, AlreadyConnectedException {
        AccessBase accessBase = accessBaseMap.get(opcServer.getKeyWord());
        if (accessBase==null){
            accessBase = new SyncAccess(openServer(opcServer),1000);
            if (accessBase.isActive()){
                accessBaseMap.put(opcServer.getKeyWord(),accessBase);
            }
            return accessBase;
        }else {
            return accessBase;
        }
    }
    /**
    * @Description 获取所有已连接的数据库
    * @Author sxmz
    * @Date 2021/5/14 0014 下午 4:06
    **/
    @Override
    public List<Server> getConnectServer(){
        List<Server> list = new ArrayList<>();
        for (Map.Entry<String,Server> entry: serverMap.entrySet()){
            list.add(entry.getValue());
        }
        return list;
    }

    /**
    * @Description opc服务器断开连接
    * @Return
    * @Author sxmz
    * @Date 2021/5/11 0011 下午 3:55
    **/
    @Override
    public Boolean disposeServer(OPCServer opcServer){
        Server server = serverMap.get(opcServer.getKeyWord());
        if (server == null){
            System.out.println("当前服务器不在连接状态！请检查请求参数！");
            return false;
        }else {
            server.dispose();
            serverMap.remove(opcServer.getKeyWord());
            System.out.println(opcServer.getHost()+" 的 "+opcServer.getDomain()+" 服务器已断开连接...");
            return true;
        }
    }

    @Override
    public IPage<OPCServer> selectOPCServerPage(IPage<OPCServer> page, OPCServer opcServer) {
        return page.setRecords(baseMapper.selectOPCServerPage(page, opcServer));
    }

}
